package com.glsc.ngateway.opmanage.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.util.CollectionUtils;
import com.glsc.ngateway.common.api.common.ex.GatewayException;
import com.glsc.ngateway.common.api.common.ex.Result;
import com.glsc.ngateway.common.api.common.utils.JsonUtil;
import com.glsc.ngateway.common.api.flowable.dto.demand.FileType;
import com.glsc.ngateway.common.api.flowable.dto.demand.FlowableAppendDto;
import com.glsc.ngateway.common.api.flowable.dto.demand.ReportShowResponse;
import com.glsc.ngateway.common.api.flowable.feign.IFeignFlowableService;
import com.glsc.ngateway.common.api.flowable.resp.FlowableResponse;
import com.glsc.ngateway.common.api.flowable.resp.ResponseUploadDto;
import com.glsc.ngateway.common.api.platform.resp.PlatformResponse;
import com.glsc.ngateway.opmanage.utils.TokenUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping(value = "/common")
public class CommonController {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    IFeignFlowableService feignDemandService;

    @Autowired
    TokenUtil tokenUtil;

    @Value("${demand.downloadUrl}")
    String downloadUrl;


    @RequestMapping(method = RequestMethod.POST, value = "uploadDoc")
    public PlatformResponse<List<Map<String, String>>> uploadDoc(HttpServletRequest request, @RequestPart(value = "file") MultipartFile[] file) {
        PlatformResponse<List<Map<String, String>>> ret = new PlatformResponse();
        try {
            //1.调用网关系统上传文件
            FlowableResponse<ResponseUploadDto> nwret = feignDemandService.uploadDoc(file);
            if (nwret.getStatus() == 0) {
                //"annexId": "http://10.1.81.200:12580/flowable/common/oaDownloadAppendix/ee7ded5a-2198-4d56-a44d-b2af055e227d",
                //"annexName": "需求测试文档.docx"
                List<Map<String, String>> list = (List<Map<String, String>>) nwret.getData().getFileList();
                list.forEach(r -> {
                    r.put("appendixId", r.get("annexId").substring(r.get("annexId").lastIndexOf("/") + 1));
                    r.put("appendixName", r.get("annexName"));
                });

                ret = PlatformResponse.successData(list);
            } else {
                ret = PlatformResponse.failedMsg(nwret.getMsg());
            }

        } catch (Exception e) {
            ret = PlatformResponse.failedMsg(e.getMessage());
            logger.error("uploadDoc异常！", e);
        }

        return ret;
    }


    @RequestMapping(method = RequestMethod.GET, value = "downloadDoc")
    public PlatformResponse<byte[]> downloadDoc(@RequestParam(value = "appendixId", required = true) String appendixId) {
        PlatformResponse<byte[]> ret = null;

        try {
            ResponseEntity<byte[]> nwret = feignDemandService.downloadDemandAppendix(appendixId);
            if (nwret != null) {
                ret = PlatformResponse.successData(nwret.getBody());
            } else {
                ret = PlatformResponse.failedMsg("文件下载失败");
            }

        } catch (Exception e) {
            ret = PlatformResponse.failedMsg(e.getMessage());
            logger.error("downloadDoc异常！", e);
        }

        return ret;
    }

    @RequestMapping(method = RequestMethod.GET, value = "showDoc")
    public PlatformResponse<ReportShowResponse> show(@RequestParam(value = "appendixId", required = true) String appendixId,
                                                     @RequestParam(value = "appendixName", required = true) String appendixName) {
        PlatformResponse<ReportShowResponse> ret = null;
        try {
            String title = appendixName;
            String url = downloadUrl + appendixId;
            String token = tokenUtil.generateToken(JsonUtil.Obj2Str(new ReportShowResponse(title, url, FileType.valueOf(appendixName.substring(appendixName.lastIndexOf(".") + 1)))));

            ReportShowResponse resdata = new ReportShowResponse(title, url, token, FileType.valueOf(appendixName.substring(appendixName.lastIndexOf(".") + 1)));
            ret = PlatformResponse.successData(resdata);
            ret.setFileId(title);
        } catch (Exception e) {
            ret = PlatformResponse.failedMsg(e.getMessage());
        }

        return ret;
    }

    @GetMapping("/getContentZipByDocIds")
    @ApiOperation(value = "根据档案Ids批量下载zip文件", notes = "根据档案Ids批量下载zip文件")
    public Object getContentZipByDocIds(@ApiParam(required = true, value = "档案IDs") @RequestParam String docIds, @ApiParam(value = "zip文件名") @RequestParam(required = false) String zipFileName
            , HttpServletRequest request
            , HttpServletResponse response) throws IOException {
        if (StrUtil.isEmpty(docIds)) {
            throw GatewayException.error("查询档案IDs不合法");
        }
        String[] docIdArr = docIds.split(",");
        List<String> docIdList = new ArrayList<>();
        for(String docIdStr:docIdArr){
            docIdList.add(docIdStr);
        }
        logger.info("根据档案Ids批量下载zip文件,docIdList:" + docIdList);
        ResponseEntity<List<FlowableAppendDto>> appendInfos = feignDemandService.getAppendixInfos(docIdList);
        List<FlowableAppendDto> documentInfoList = appendInfos.getBody();

        if (CollectionUtils.isEmpty(documentInfoList)) {
            return Result.fail("档案列表不存在或文件名为空");
        }

        //设置压缩包的名字
        //解决不同浏览器压缩包名字含有中文时乱码的问题
        if(StrUtil.isEmpty(zipFileName)){
            zipFileName = "事件报告附件合集.zip";
        }
        if(!zipFileName.endsWith(".zip")){
            zipFileName = zipFileName + ".zip";
        }
        String userAgent = request.getHeader("User-Agent");
        // 针对IE或者以IE为内核的浏览器：
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            zipFileName = java.net.URLEncoder.encode(zipFileName, "UTF-8");
        } else {
            // 非IE浏览器的处理：
            zipFileName = new String(zipFileName.getBytes("UTF-8"), "ISO-8859-1");
        }
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", "attachment;filename="+ zipFileName);
        //设置压缩流：直接写入response，实现边压缩边下载
        ZipOutputStream zipos =null;
        try{
            zipos=new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            zipos.setMethod(ZipOutputStream.DEFLATED);//设置压缩方法
        }catch(Exception e){
            e.printStackTrace();
        }
        DataOutputStream os=null;
        //处理重名文件
        Map<String,Long> fileNameMap = documentInfoList.parallelStream().collect(Collectors.groupingBy(FlowableAppendDto::getAppendixName,Collectors.counting()));
        //循环将文件写入压缩流
        for(int i=0;i<documentInfoList.size();i++){
            String filePath=documentInfoList.get(i).getAppendixPath();
            String fileName=documentInfoList.get(i).getAppendixName();
            File file=new File(filePath);//要下载文件的路径
            try{
                //添加ZipEntry，并ZipEntry中写入文件流
                //处理同名文件
                if (fileNameMap.get(fileName) > 1){
                    fileName = reNameFileName(fileName,documentInfoList,i);
                }
                zipos.putNextEntry(new ZipEntry(fileName));
                os=new DataOutputStream(zipos);
                InputStream is=new FileInputStream(file);
                byte[] b = new byte[100];
                int length = 0;
                while((length = is.read(b))!= -1){
                    os.write(b, 0, length);
                }
                is.close();
                zipos.closeEntry();
            }catch(Exception e){
                logger.error("根据档案Ids批量下载zip文件异常:", e);
            }
        }
        //关闭流
        try {
            os.flush();
            os.close();
            zipos.close();
        } catch (IOException e) {
            logger.error("根据档案Ids批量下载zip文件关闭流异常:", e);
            return null;
        }
        return null;
    }


    /**
     * 重名文件重命名
     * @param fileName
     * @param documentInfoList
     * @param i
     * @return
     */
    private String reNameFileName(String fileName, List<FlowableAppendDto> documentInfoList, int i) {
        int index = 0;
        for (int j = 0; j < documentInfoList.size(); j++) {
            if (documentInfoList.get(j).getAppendixName().equals(fileName)){
                if (j != i){
                    index ++;
                } else {
                    //为了防止文件名称带.
                    int lastIndex = fileName.lastIndexOf(".");
                    if (index != 0){
                        return fileName.substring(0,lastIndex)+"（"+index+"）"+fileName.substring(lastIndex);
                    } else {
                        return fileName;
                    }
                }
            }
        }
        return fileName;
    }


}
